home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Freeware / Miro 1.0 / Miro_Installer.exe / Miro_Downloader.exe / selection.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2007-11-12  |  19.4 KB  |  687 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.5)
  3.  
  4. '''Handle selection.'''
  5. from copy import copy
  6. import app
  7. import database
  8. import eventloop
  9. import folder
  10. import guide
  11. import item
  12. import tabs
  13. import playlist
  14. import feed
  15. import views
  16. import template
  17. import util
  18. from gtcache import gettext as _
  19.  
  20. def getID(obj):
  21.     '''Gets an ID to use for an object.  For tabs, this is the object ID that
  22.     maps to the tab.  For other objects this is the actual DDBObject ID.'''
  23.     if isinstance(obj, tabs.Tab):
  24.         return obj.objID()
  25.     else:
  26.         return obj.getID()
  27.  
  28.  
  29. class SelectionArea(object):
  30.     '''Represents an area that holds a selection.  Currently we have 2
  31.     SelectionAreas, the tab list and the item list.  SelectionAreas hold
  32.     several database views, for instance the tab list contains
  33.     views.guideTabs, views.staticTabs, views.feedTabs and views.playlistTabs.
  34.     All the items selected in an area must be in a single view.
  35.  
  36.     Member variables:
  37.  
  38.     currentView -- The view that items are currently selected in, or None if
  39.         there are no items selected.
  40.     currentSelection -- set of object IDs that are currently selected.
  41.     '''
  42.     
  43.     def __init__(self, selectionHandler):
  44.         self.currentSelection = set()
  45.         self.currentView = None
  46.         self.handler = selectionHandler
  47.  
  48.     
  49.     def switchView(self, view):
  50.         if self.currentView == view:
  51.             return None
  52.         
  53.         if self.currentView:
  54.             self.clearSelection()
  55.         
  56.         self.currentView = view
  57.         self.currentView.addRemoveCallback(self.onRemove)
  58.         self.currentView.addAddCallback(self.onAdd)
  59.         self.currentView.addViewUnlinkCallback(self.onViewUnlinked)
  60.  
  61.     
  62.     def selectItem(self, view, id):
  63.         self.switchView(view)
  64.         obj = view.getObjectByID(id)
  65.         self.currentSelection.add(id)
  66.         obj.setSelected(True)
  67.  
  68.     
  69.     def deselectItem(self, view, id):
  70.         if view != self.currentView:
  71.             raise ValueError('view != current view in deselectItem()')
  72.         
  73.         obj = view.getObjectByID(id)
  74.         self.currentSelection.remove(id)
  75.         obj.setSelected(False)
  76.  
  77.     
  78.     def isSelected(self, view, id):
  79.         if self.currentView == view:
  80.             pass
  81.         return id in self.currentSelection
  82.  
  83.     
  84.     def toggleItemSelect(self, view, id):
  85.         self.switchView(view)
  86.         if id in self.currentSelection:
  87.             self.deselectItem(view, id)
  88.         else:
  89.             self.selectItem(view, id)
  90.  
  91.     
  92.     def clearSelection(self):
  93.         '''Clears the current selection.'''
  94.         for obj in self.getObjects():
  95.             obj.setSelected(False)
  96.         
  97.         self.currentSelection = set()
  98.         if self.currentView is not None:
  99.             self.currentView.removeRemoveCallback(self.onRemove)
  100.             self.currentView.removeAddCallback(self.onAdd)
  101.             self.currentView = None
  102.         
  103.  
  104.     
  105.     def selectAll(self):
  106.         '''Select all objects in the current View.'''
  107.         view = self.currentView
  108.         if view:
  109.             for obj in view:
  110.                 if obj.getID not in self.currentSelection:
  111.                     self.selectItem(view, obj.getID())
  112.                     continue
  113.             
  114.         
  115.  
  116.     
  117.     def calcExtendRange(self, view, id):
  118.         idIsBefore = False
  119.         gotFirst = False
  120.         firstID = None
  121.         lastID = None
  122.         for obj in view:
  123.             objID = getID(obj)
  124.             if objID == id and not gotFirst:
  125.                 idIsBefore = True
  126.             
  127.             if objID in self.currentSelection:
  128.                 if not gotFirst:
  129.                     firstID = objID
  130.                     gotFirst = True
  131.                 
  132.                 lastID = objID
  133.                 continue
  134.         
  135.         if firstID is None or lastID is None:
  136.             raise AssertionError("Couldn't find my selected IDs")
  137.         
  138.         if idIsBefore:
  139.             return (id, lastID)
  140.         else:
  141.             return (firstID, id)
  142.  
  143.     
  144.     def extendSelection(self, view, id):
  145.         '''Extends the selection in response to a shift-select.  If id is on
  146.         top of the current selection, we will select everything between the id
  147.         and the last selected item.  If id is below it or in the middle, we
  148.         will select between the first selected item and id.  
  149.         '''
  150.         self.switchView(view)
  151.         if len(self.currentSelection) == 0:
  152.             return self.selectItem(view, id)
  153.         
  154.         (firstID, lastID) = self.calcExtendRange(view, id)
  155.         self.selectBetween(view, firstID, lastID)
  156.  
  157.     
  158.     def selectBetween(self, view, firstID, lastID):
  159.         '''Select all items in view between firstID and lastID.'''
  160.         self.switchView(view)
  161.         selecting = False
  162.         toSelect = []
  163.         for obj in view:
  164.             id = getID(obj)
  165.             if selecting and id not in self.currentSelection:
  166.                 toSelect.append(id)
  167.             
  168.             if id == firstID:
  169.                 selecting = True
  170.                 if id not in self.currentSelection:
  171.                     toSelect.append(id)
  172.                 
  173.             
  174.             if id == lastID:
  175.                 break
  176.                 continue
  177.         
  178.         for id in toSelect:
  179.             self.selectItem(view, id)
  180.         
  181.  
  182.     
  183.     def onRemove(self, obj, id):
  184.         if id in self.currentSelection:
  185.             self.currentSelection.remove(id)
  186.             if obj.idExists():
  187.                 obj.setSelected(False)
  188.             
  189.         
  190.  
  191.     
  192.     def setObjectsActive(self, newValue):
  193.         '''Iterate through all selected objects and call setActive on them,
  194.         passing in newValue.
  195.         '''
  196.         for obj in self.getObjects():
  197.             obj.setActive(newValue)
  198.         
  199.  
  200.     
  201.     def onAdd(self, obj, id):
  202.         if obj.getSelected() and id not in self.currentSelection:
  203.             self.currentSelection.add(id)
  204.         
  205.  
  206.     
  207.     def onViewUnlinked(self):
  208.         self.clearSelection()
  209.  
  210.     
  211.     def getTypesDetailed(self):
  212.         """Get the type of objects that are selected.  
  213.  
  214.         Returns a set, containing all the type of objects selected.  The
  215.         members will be one of the following:
  216.  
  217.         'item', 'downloadeditem' 'playlisttab', playlistfoldertab,
  218.         'channeltab', 'channelfoldertab', 'guidetab', 'addedguidetab',
  219.         'statictab'.
  220.  
  221.         """
  222.         types = set()
  223.         for obj in self.getObjects():
  224.             if isinstance(obj, item.Item):
  225.                 if obj.isDownloaded():
  226.                     newType = 'downloadeditem'
  227.                 else:
  228.                     newType = 'item'
  229.             elif isinstance(obj, tabs.Tab):
  230.                 objClass = obj.obj.__class__
  231.                 if objClass == playlist.SavedPlaylist:
  232.                     newType = 'playlisttab'
  233.                 elif objClass == folder.PlaylistFolder:
  234.                     newType = 'playlistfoldertab'
  235.                 elif objClass == feed.Feed:
  236.                     newType = 'channeltab'
  237.                 elif objClass == folder.ChannelFolder:
  238.                     newType = 'channelfoldertab'
  239.                 elif objClass == guide.ChannelGuide:
  240.                     if obj.obj.getDefault():
  241.                         newType = 'guidetab'
  242.                     else:
  243.                         newType = 'addedguidetab'
  244.                 elif objClass == tabs.StaticTab:
  245.                     newType = 'statictab'
  246.                 else:
  247.                     raise ValueError('Bad selected tab type: %s' % obj.obj)
  248.             else:
  249.                 raise ValueError('Bad selected object type: %s' % obj)
  250.             types.add(newType)
  251.         
  252.         self.simplifyTypes(types)
  253.         return types
  254.  
  255.     
  256.     def simplifyTypes(self, types):
  257.         if len(types) == 0:
  258.             return None
  259.         elif types.issubset(set([
  260.             'item',
  261.             'downloadeditem'])):
  262.             return 'item'
  263.         elif types.issubset(set([
  264.             'playlistfoldertab',
  265.             'playlisttab'])):
  266.             return 'playlisttab'
  267.         elif types.issubset(set([
  268.             'channelfoldertab',
  269.             'channeltab'])):
  270.             return 'channeltab'
  271.         elif len(types) == 1:
  272.             for type in types:
  273.                 return type
  274.             
  275.         else:
  276.             raise ValueError('Multiple types selected: %s' % types)
  277.  
  278.     
  279.     def getType(self):
  280.         '''Get the simplified version of the type of objects that are
  281.         selected.  getType() works like getTypesDetailed(), but it just
  282.         returns one value.  It doesn\'t differentiate between playlists and
  283.         playlist folders, and items and downloaded items for example.
  284.  
  285.         The return value will be one of
  286.  
  287.         "item", "playlisttab", "channeltab", \'guidetab\', \'addedguidetab\',
  288.         \'statictab\', or None if nothing is selected.  
  289.  
  290.         '''
  291.         return self.simplifyTypes(self.getTypesDetailed())
  292.  
  293.     
  294.     def getObjects(self):
  295.         view = self.currentView
  296.         return [ view.getObjectByID(id) for id in self.currentSelection ]
  297.  
  298.     
  299.     def firstBeforeSelection(self, iterator):
  300.         '''Go through iterator and find the first item that is selected.
  301.         Returns the item immediately before that one.
  302.  
  303.         Returns None if the first item in iterator is selected, or no items
  304.         are selected.
  305.         '''
  306.         lastItem = None
  307.         for item in iterator:
  308.             if item.getID() in self.currentSelection:
  309.                 return lastItem
  310.             
  311.             lastItem = item
  312.         
  313.         return None
  314.  
  315.     
  316.     def firstAfterSelection(self, iterator):
  317.         '''Like firstBeforeSelection, but returns the first item following the
  318.         last selected item in iterator.
  319.         '''
  320.         retval = None
  321.         lastSelected = False
  322.         for item in iterator:
  323.             if item.getID() in self.currentSelection:
  324.                 lastSelected = True
  325.                 continue
  326.             if lastSelected:
  327.                 lastSelected = False
  328.                 retval = item
  329.                 continue
  330.         
  331.         return retval
  332.  
  333.  
  334.  
  335. class TabSelectionArea(SelectionArea):
  336.     '''Selection area for the tablist.  This has a couple special cases to
  337.     ensure that we always have at least one tab selected.
  338.     '''
  339.     
  340.     def selectItem(self, view, id):
  341.         SelectionArea.selectItem(self, view, id)
  342.         self.moveCursorToSelection()
  343.  
  344.     
  345.     def deselectItem(self, view, id):
  346.         SelectionArea.deselectItem(self, view, id)
  347.         self.moveCursorToSelection()
  348.  
  349.     
  350.     def moveCursorToSelection(self):
  351.         for id in self.currentSelection:
  352.             self.currentView.moveCursorToID(id)
  353.         
  354.  
  355.     
  356.     def toggleItemSelect(self, view, id):
  357.         if self.currentSelection == set([
  358.             id]):
  359.             return None
  360.         else:
  361.             return SelectionArea.toggleItemSelect(self, view, id)
  362.  
  363.     
  364.     def onRemove(self, obj, id):
  365.         SelectionArea.onRemove(self, obj, id)
  366.         eventloop.addUrgentCall(self.checkNoTabsSelected, 'checkNoTabsSelected')
  367.  
  368.     
  369.     def checkNoTabsSelected(self):
  370.         if len(self.currentSelection) == 0:
  371.             prevTab = self.currentView.cur()
  372.             if prevTab is None:
  373.                 prevTab = self.currentView.getNext()
  374.             
  375.             if prevTab is None:
  376.                 self.selectFirstGuide()
  377.             else:
  378.                 self.selectItem(self.currentView, prevTab.objID())
  379.             self.handler.displayCurrentTabContent()
  380.         
  381.  
  382.     
  383.     def selectFirstGuide(self):
  384.         views.guideTabs.resetCursor()
  385.         guide = views.guideTabs.getNext()
  386.         self.selectItem(views.guideTabs, guide.objID())
  387.         self.handler.displayCurrentTabContent()
  388.  
  389.     
  390.     def isFolderSelected(self):
  391.         '''Returns if a channel/playlist folder is selected.'''
  392.         for tab in self.getObjects():
  393.             if isinstance(tab.obj, folder.FolderBase):
  394.                 return True
  395.                 continue
  396.         
  397.         return False
  398.  
  399.  
  400.  
  401. class SelectionHandler(object):
  402.     '''Handles selection for Democracy.
  403.  
  404.     Attributes:
  405.  
  406.     tabListSelection -- SelectionArea for the tab list
  407.     itemListSelection -- SelectionArea for the item list
  408.     tabListActive -- does the tabListSelection the have the "active"
  409.         selection?  In other words, is that the one that was clicked on last.
  410.     '''
  411.     
  412.     def __init__(self):
  413.         self.tabListSelection = TabSelectionArea(self)
  414.         self.itemListSelection = SelectionArea(self)
  415.         self.lastDisplay = None
  416.         self.tabListActive = True
  417.  
  418.     
  419.     def getSelectionForArea(self, area):
  420.         if area == 'tablist':
  421.             return self.tabListSelection
  422.         elif area == 'itemlist':
  423.             return self.itemListSelection
  424.         else:
  425.             raise ValueError('Unknown area: %s' % area)
  426.  
  427.     
  428.     def isSelected(self, area, view, id):
  429.         return self.getSelectionForArea(area).isSelected(view, id)
  430.  
  431.     
  432.     def selectItem(self, area, view, id, shiftSelect, controlSelect, displayTabContent = True):
  433.         selection = self.getSelectionForArea(area)
  434.         
  435.         try:
  436.             selectedObj = view.getObjectByID(id)
  437.         except database.ObjectNotFoundError:
  438.             return None
  439.  
  440.         if isinstance(selectedObj, tabs.Tab) and selectedObj.type in ('statictab', 'guide'):
  441.             controlSelect = shiftSelect = False
  442.         
  443.         if controlSelect:
  444.             selection.toggleItemSelect(view, id)
  445.         elif shiftSelect:
  446.             selection.extendSelection(view, id)
  447.         else:
  448.             selection.clearSelection()
  449.             selection.selectItem(view, id)
  450.         if area == 'itemlist':
  451.             self.setTabListActive(False)
  452.             self.updateMenus()
  453.         else:
  454.             self.setTabListActive(True)
  455.             if displayTabContent:
  456.                 self.displayCurrentTabContent()
  457.             
  458.  
  459.     
  460.     def setTabListActive(self, value):
  461.         self.tabListActive = value
  462.         self.tabListSelection.setObjectsActive(value)
  463.         self.itemListSelection.setObjectsActive(not value)
  464.  
  465.     
  466.     def calcSelection(self, area, sourceID):
  467.         '''Calculate the selection, given the ID of an object that was clicked
  468.         on.  If sourceID is in the current selection, this will all the
  469.         objects in the current selection, otherwise it will be only the object
  470.         that corresponds to sourceID.  
  471.         '''
  472.         selection = self.getSelectionForArea(area)
  473.         if sourceID in selection.currentSelection:
  474.             return set(selection.currentSelection)
  475.         else:
  476.             return set([
  477.                 sourceID])
  478.  
  479.     
  480.     def selectFirstGuide(self):
  481.         self.tabListSelection.selectFirstGuide()
  482.  
  483.     
  484.     def selectTabByTemplateBase(self, tabTemplateBase, displayTabContent = True):
  485.         tabViews = [
  486.             views.guideTabs,
  487.             views.staticTabs,
  488.             views.feedTabs,
  489.             views.playlistTabs]
  490.         for view in tabViews:
  491.             for tab in view:
  492.                 if tab.tabTemplateBase == tabTemplateBase:
  493.                     self.selectItem('tablist', view, tab.objID(), shiftSelect = False, controlSelect = False, displayTabContent = displayTabContent)
  494.                     return None
  495.                     continue
  496.             
  497.         
  498.  
  499.     
  500.     def selectTabByObject(self, obj, displayTabContent = True):
  501.         channelTabOrder = util.getSingletonDDBObject(views.channelTabOrder)
  502.         playlistTabOrder = util.getSingletonDDBObject(views.playlistTabOrder)
  503.         tabViews = [
  504.             views.guideTabs,
  505.             views.staticTabs,
  506.             channelTabOrder.getView(),
  507.             playlistTabOrder.getView()]
  508.         for view in tabViews:
  509.             for tab in view:
  510.                 if tab.obj is obj:
  511.                     self.selectItem('tablist', view, tab.objID(), shiftSelect = False, controlSelect = False, displayTabContent = displayTabContent)
  512.                     return None
  513.                     continue
  514.             
  515.         
  516.  
  517.     
  518.     def _chooseDisplayForCurrentTab(self):
  519.         tls = self.tabListSelection
  520.         frame = app.controller.frame
  521.         if len(tls.currentSelection) == 0:
  522.             raise AssertionError('No tabs selected')
  523.         elif len(tls.currentSelection) == 1:
  524.             for id in tls.currentSelection:
  525.                 tab = tls.currentView.getObjectByID(id)
  526.                 return app.TemplateDisplay(tab.contentsTemplate, tab.templateState, frameHint = frame, areaHint = frame.mainDisplay, id = tab.obj.getID())
  527.             
  528.         else:
  529.             foldersSelected = False
  530.             type = tls.getType()
  531.             if type == 'playlisttab':
  532.                 templateName = 'multi-playlist'
  533.             elif type == 'channeltab':
  534.                 templateName = 'multi-channel'
  535.             
  536.             selectedChildren = 0
  537.             selectedFolders = 0
  538.             containedChildren = 0
  539.             for tab in self.getSelectedTabs():
  540.                 if isinstance(tab.obj, folder.FolderBase):
  541.                     selectedFolders += 1
  542.                     view = tab.obj.getChildrenView()
  543.                     containedChildren += view.len()
  544.                     for child in view:
  545.                         if child.getID() in tls.currentSelection:
  546.                             selectedChildren -= 1
  547.                             continue
  548.                     
  549.                 selectedChildren += 1
  550.             
  551.             return app.TemplateDisplay(templateName, 'default', frameHint = frame, areaHint = frame.mainDisplay, selectedFolders = selectedFolders, selectedChildren = selectedChildren, containedChildren = containedChildren)
  552.  
  553.     
  554.     def updateMenus(self):
  555.         tabTypes = self.tabListSelection.getTypesDetailed()
  556.         if tabTypes.issubset(set([
  557.             'guidetab',
  558.             'addedguidetab'])):
  559.             guideURL = self.getSelectedTabs()[0].obj.getURL()
  560.         else:
  561.             guideURL = None
  562.         multiple = len(self.tabListSelection.currentSelection) > 1
  563.         actionGroups = { }
  564.         states = {
  565.             'plural': [],
  566.             'folders': [],
  567.             'folder': [] }
  568.         is_playlistlike = tabTypes.issubset(set([
  569.             'playlisttab',
  570.             'playlistfoldertab']))
  571.         is_channellike = tabTypes.issubset(set([
  572.             'channeltab',
  573.             'channelfoldertab',
  574.             'addedguidetab']))
  575.         is_channel = tabTypes.issubset(set([
  576.             'channeltab',
  577.             'channelfoldertab']))
  578.         if len(tabTypes) == 1:
  579.             if multiple:
  580.                 if 'playlisttab' in tabTypes:
  581.                     states['plural'].append('RemovePlaylists')
  582.                 elif 'playlistfoldertab' in tabTypes:
  583.                     states['folders'].append('RemovePlaylists')
  584.                 elif 'channeltab' in tabTypes:
  585.                     states['plural'].append('RemoveChannels')
  586.                 elif 'channelfoldertab' in tabTypes:
  587.                     states['folders'].append('RemoveChannels')
  588.                 elif 'addedguidetab' in tabTypes:
  589.                     states['plural'].append('ChannelGuides')
  590.                 
  591.             elif 'playlisttab' in tabTypes:
  592.                 pass
  593.             elif 'playlistfoldertab' in tabTypes:
  594.                 states['folder'].append('RemovePlaylists')
  595.             elif 'channeltab' in tabTypes:
  596.                 pass
  597.             elif 'channelfoldertab' in tabTypes:
  598.                 states['folder'].append('RemoveChannels')
  599.             elif 'addedguidetab' in tabTypes:
  600.                 pass
  601.             
  602.         
  603.         if multiple and is_channel:
  604.             states['plural'].append('UpdateChannels')
  605.         
  606.         if is_channellike:
  607.             pass
  608.         actionGroups['ChannelLikeSelected'] = not multiple
  609.         actionGroups['ChannelLikesSelected'] = is_channellike
  610.         if is_playlistlike:
  611.             pass
  612.         actionGroups['PlaylistLikeSelected'] = not multiple
  613.         actionGroups['PlaylistLikesSelected'] = is_playlistlike
  614.         if tabTypes.issubset(set([
  615.             'channeltab'])):
  616.             pass
  617.         actionGroups['ChannelSelected'] = not multiple
  618.         actionGroups['ChannelsSelected'] = tabTypes.issubset(set([
  619.             'channeltab',
  620.             'channelfoldertab']))
  621.         if tabTypes.issubset(set([
  622.             'channelfoldertab'])):
  623.             pass
  624.         actionGroups['ChannelFolderSelected'] = not multiple
  625.         actionGroups['VideoSelected'] = False
  626.         actionGroups['VideosSelected'] = False
  627.         actionGroups['VideoPlayable'] = False
  628.         videoFileName = None
  629.         if 'downloadeditem' in self.itemListSelection.getTypesDetailed():
  630.             actionGroups['VideosSelected'] = True
  631.             actionGroups['VideoPlayable'] = True
  632.             if len(self.itemListSelection.currentSelection) == 1:
  633.                 actionGroups['VideoSelected'] = True
  634.                 item = self.itemListSelection.getObjects()[0]
  635.                 videoFileName = item.getVideoFilename()
  636.             else:
  637.                 states['plural'].append('RemoveVideos')
  638.         
  639.         app.controller.frame.onSelectedTabChange(states, actionGroups, guideURL, videoFileName)
  640.  
  641.     
  642.     def displayCurrentTabContent(self):
  643.         frame = app.controller.frame
  644.         mainDisplay = frame.getDisplay(frame.mainDisplay)
  645.         if mainDisplay and hasattr(mainDisplay, 'templateName') and mainDisplay.templateName == 'channel':
  646.             tls = self.tabListSelection
  647.             if len(tls.currentSelection) == 1:
  648.                 for id in tls.currentSelection:
  649.                     tab = tls.currentView.getObjectByID(id)
  650.                     if tab.contentsTemplate == 'channel':
  651.                         newId = int(tab.obj.getID())
  652.                         self.itemListSelection.clearSelection()
  653.                         self.updateMenus()
  654.                         if mainDisplay.kargs['id'] != newId:
  655.                             mainDisplay.reInit(id = newId)
  656.                         
  657.                         return None
  658.                         continue
  659.                 
  660.             
  661.         
  662.         newDisplay = self._chooseDisplayForCurrentTab()
  663.         if self.lastDisplay and newDisplay == self.lastDisplay and self.lastDisplay is mainDisplay and newDisplay.templateName != 'guide':
  664.             newDisplay.unlink()
  665.             return None
  666.         
  667.         self.itemListSelection.clearSelection()
  668.         self.updateMenus()
  669.         template.queueSelectDisplay(frame, newDisplay, frame.mainDisplay)
  670.         self.lastDisplay = newDisplay
  671.  
  672.     
  673.     def isTabSelected(self, tab):
  674.         return tab.objID() in self.tabListSelection.currentSelection
  675.  
  676.     
  677.     def getSelectedTabs(self):
  678.         '''Return a list of the currently selected Tabs. '''
  679.         return self.tabListSelection.getObjects()
  680.  
  681.     
  682.     def getSelectedItems(self):
  683.         '''Return a list of the currently selected items. '''
  684.         return self.itemListSelection.getObjects()
  685.  
  686.  
  687.